package com.gome.ocean.service.authority.impl;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gome.framework.util.StringUtil;
import com.gome.ocean.common.constants.Constants;
import com.gome.ocean.common.exception.AuthorityManagerException;
import com.gome.ocean.dao.model.authority.BaseOnProjectEntity;
import com.gome.ocean.dao.model.authority.ProjectBO;
import com.gome.ocean.dao.model.authority.User;
import com.gome.ocean.dao.model.reqres.AccessRequest;
import com.gome.ocean.dao.model.reqres.AccessResponse;
import com.gome.ocean.dao.model.reqres.UserFunctionTable;
import com.gome.ocean.service.authority.AuthorityManager;
import com.gome.ocean.service.authority.ProjectService;
import com.gome.ocean.service.base.BaseController;
import com.gome.ocean.service.utils.UserFuncTableBuilder;

/**
 * Created by liuqingxia on 2016/6/2.
 */
@Component("authorityManager")
public class AuthorityManagerImpl extends BaseController implements AuthorityManager {

    private static final String[] EXCLUDED_URLS = { "/api/context", "/api/log", "/login", "/ERROR", "/assets", "/css",
                                                    "/js", "/img", "/api/job/interruptJob" };

    private static final String LOGOUT_URL = "/logout";

    private static final String USER_FUNC_TABLE = "userFuncTable";

    @Autowired
    private ProjectService projectService;

    @Autowired
    private UserFuncTableBuilder builder;

    @Override
    public AccessResponse permitAccess(AccessRequest request) {
        String url = request.getUrl();
        HttpSession session = request.getSession();
        AccessResponse response = getAccessRes();
        if (isExcludeUrl(url) || url.equals("/")) {
            return response.permitTrue();
        }
        if (url.startsWith("/api")) return response.permitTrue();
        if (url.startsWith("/sendSms") || url.startsWith("/register/getResPage")
            || url.startsWith("/register/sendRegisterSms") || url.startsWith("/register/newRegisterUser"))
            return response.permitTrue();
        if (url.startsWith("/permissionMag/oaCallbackInterface")
            || url.startsWith("/permissionMag/checkDataUpdateStatusInterface")
            || url.startsWith("/permissionMag/funDBACallBackInterface")
            || url.startsWith("/permissionMag/validDruidDataSource")) return response.permitTrue();
        if (!hadLogin(session)) {
            return response.notLogin();
        }
        if (isLogOut(url)) {
            session.removeAttribute(USER_FUNC_TABLE);
            return response.permitTrue();
        }
        return permitAccessFunction(request, response);
    }

    @Override
    public AccessResponse permitAccess(User user, BaseOnProjectEntity entity) throws AuthorityManagerException {
        AccessResponse response = getAccessRes();
        String projectName = entity.getProject();
        if (StringUtil.isBlank(projectName)) {
            throw new IllegalArgumentException("Argument entity must have the project value");
        }
        ProjectBO projectBO = projectService.findProjectByName(projectName);
        if (null == projectBO) {
            response.setPermit(false);
            return response;
        }
        if (user.getRole().equals("admin")) {
            response.setPermit(true);
            return response;
        }
        boolean isPermit = projectBO.hasUser(user.getEmail());
        response.setPermit(isPermit);
        return response;
    }

    private boolean isExcludeUrl(String url) {
        for (String excludeUrl : EXCLUDED_URLS) {
            if (url.startsWith(excludeUrl)) {
                return true;
            }
        }
        return false;
    }

    private boolean hadLogin(HttpSession session) {
        User user = (User) session.getAttribute(Constants.SESSION_LOGIN_USER);
        return null != user;
    }

    private boolean isLogOut(String url) {
        return url.equals(LOGOUT_URL);
    }

    private AccessResponse permitAccessFunction(AccessRequest request, AccessResponse response) {
        UserFunctionTable functionTable = getUserFuncTable(request);
        if (null == functionTable) {
            functionTable = buildUserFuncTable(request);
            addUserFuncTable(request, functionTable);
        }
        String url = request.getUrl();
        String methodType = request.getType().getTypeStr();
        if (functionTable.haveFunction(url, methodType)) {
            return response.permitTrue();
        }
        return response.setErrorMsg("您没有访问该功能(" + url + ",类型：" + methodType + ")的权限");
    }

    private HttpSession getSession(AccessRequest request) {
        return request.getSession();
    }

    private User getUser(AccessRequest request) {
        HttpSession session = getSession(request);
        return (User) session.getAttribute(Constants.SESSION_LOGIN_USER);
    }

    private UserFunctionTable getUserFuncTable(AccessRequest request) {
        HttpSession session = getSession(request);
        return (UserFunctionTable) session.getAttribute(USER_FUNC_TABLE);
    }

    private void addUserFuncTable(AccessRequest request, UserFunctionTable userFuncTable) {
        HttpSession session = getSession(request);
        session.setAttribute(USER_FUNC_TABLE, userFuncTable);
    }

    private UserFunctionTable buildUserFuncTable(AccessRequest request) {
        return buildUserFuncTable(getUser(request));
    }

    private UserFunctionTable buildUserFuncTable(User user) {
        return builder.build(user);
    }

    private AccessResponse getAccessRes() {
        return new AccessResponse();
    }
}
